<?php

namespace api\mobile;

use think\facade\Db;
use app\common\model\Mobile;

/**
 * 北京高阳捷迅信息技术有限公司[这家没跑了]
 */
class Pay19 extends BaseModel
{
    private $notifyTable = 'mobile_notify_gaoyang';

    private $product = [
        '福建-联通-50' => 1016,
        '福建-联通-100' => 1017,
        '福建-联通-200' => 1018,
        '安徽-联通-50' => 1020,
        '安徽-联通-100' => 1021,
        '安徽-联通-200' => 1022,
        '广东-联通-50' => 1024,
        '广东-联通-100' => 1025,
        '广东-联通-200' => 1026,
        '贵州-联通-50' => 1028,
        '贵州-联通-100' => 1029,
        '贵州-联通-200' => 1030,
        '湖北-联通-50' => 1032,
        '湖北-联通-100' => 1033,
        '湖北-联通-200' => 1034,
        '新疆-联通-50' => 1036,
        '新疆-联通-100' => 1037,
        '新疆-联通-200' => 1038,
        '陕西-联通-200' => 1041,
        '西藏-联通-50' => 1063,
        '西藏-联通-100' => 1064,
        '西藏-联通-200' => 1066,
        '青海-联通-50' => 1085,
        '青海-联通-100' => 1086,
        '青海-联通-200' => 1088,
        '辽宁-电信-100' => 11207,
        '辽宁-电信-200' => 11209,
        '上海-电信-100' => 11263,
        '北京-电信-100' => 11264,
        '北京-电信-200' => 11265,
        '重庆-电信-100' => 11271,
        '重庆-电信-200' => 11272,
        '河北-电信-100' => 11277,
        '河北-电信-200' => 11278,
        '山西-电信-100' => 11283,
        '上海-电信-200' => 11284,
        '天津-电信-100' => 11289,
        '天津-电信-200' => 11290,
        '江苏-电信-100' => 11296,
        '江苏-电信-200' => 11297,
        '浙江-电信-100' => 11302,
        '浙江-电信-200' => 11303,
        '山西-电信-200' => 11304,
        '内蒙古-电信-100' => 11309,
        '内蒙古-电信-200' => 11310,
        '吉林-电信-100' => 11315,
        '吉林-电信-200' => 11316,
        '黑龙江-电信-100' => 11321,
        '黑龙江-电信-200' => 11322,
        '安徽-电信-100' => 11328,
        '安徽-电信-200' => 11329,
        '福建-电信-100' => 11334,
        '福建-电信-200' => 11335,
        '江西-电信-100' => 11340,
        '江西-电信-200' => 11341,
        '山东-电信-100' => 11346,
        '山东-电信-200' => 11347,
        '河南-电信-100' => 11352,
        '河南-电信-200' => 11353,
        '湖北-电信-100' => 11358,
        '湖北-电信-200' => 11359,
        '湖南-电信-100' => 11364,
        '湖南-电信-200' => 11365,
        '广西-电信-100' => 11370,
        '广西-电信-200' => 11371,
        '海南-电信-100' => 11376,
        '海南-电信-200' => 11377,
        '四川-电信-100' => 11382,
        '四川-电信-200' => 11383,
        '广东-电信-100' => 11387,
        '广东-电信-200' => 11388,
        '云南-电信-100' => 11393,
        '云南-电信-200' => 11394,
        '陕西-电信-100' => 11399,
        '陕西-电信-200' => 11400,
        '贵州-电信-100' => 11408,
        '贵州-电信-200' => 11409,
        '西藏-电信-100' => 11414,
        '西藏-电信-200' => 11415,
        '甘肃-电信-100' => 11420,
        '甘肃-电信-200' => 11421,
        '青海-电信-100' => 11426,
        '青海-电信-200' => 11427,
        '宁夏-电信-100' => 11432,
        '宁夏-电信-200' => 11433,
        '新疆-电信-100' => 11438,
        '新疆-电信-200' => 11439,
        '河北-联通-50' => 1238,
        '河北-联通-100' => 1239,
        '河北-联通-200' => 1241,
        '黑龙江-联通-50' => 1258,
        '黑龙江-联通-100' => 1259,
        '黑龙江-联通-200' => 1261,
        '湖南-联通-50' => 1278,
        '湖南-联通-100' => 1279,
        '湖南-联通-200' => 1281,
        '上海-联通-50' => 1662,
        '上海-联通-100' => 1663,
        '上海-联通-200' => 1665,
        '重庆-联通-50' => 1702,
        '重庆-联通-100' => 1703,
        '重庆-联通-200' => 1705,
        '吉林-联通-50' => 1802,
        '吉林-联通-100' => 1803,
        '吉林-联通-200' => 1805,
        '河南-联通-50' => 1942,
        '河南-联通-100' => 1943,
        '河南-联通-200' => 1945,
        '海南-联通-50' => 2042,
        '海南-联通-100' => 2043,
        '海南-联通-200' => 2045,
        '云南-联通-50' => 2102,
        '云南-联通-100' => 2103,
        '云南-联通-200' => 2105,
        '甘肃-联通-50' => 2162,
        '甘肃-联通-100' => 2163,
        '甘肃-联通-200' => 2165,
        '四川-联通-200' => 540,
        '北京-联通-100' => 560,
        '北京-联通-50' => 561,
        '江西-联通-50' => 562,
        '江西-联通-100' => 563,
        '陕西-联通-50' => 564,
        '陕西-联通-100' => 565,
        '山西-联通-50' => 566,
        '山西-联通-100' => 567,
        '浙江-联通-50' => 568,
        '浙江-联通-100' => 569,
        '江苏-联通-50' => 570,
        '江苏-联通-100' => 571,
        '广西-联通-50' => 572,
        '广西-联通-100' => 573,
        '山东-联通-50' => 575,
        '山东-联通-100' => 576,
        '内蒙古-联通-50' => 577,
        '内蒙古-联通-100' => 578,
        '天津-联通-50' => 580,
        '天津-联通-100' => 581,
        '江西-联通-200' => 753,
        '辽宁-联通-200' => 773,
        '四川-联通-50' => 800,
        '四川-联通-100' => 801,
        '辽宁-联通-50' => 802,
        '辽宁-联通-100' => 803,
        '北京-移动-50' => 8062,
        '上海-移动-50' => 8063,
        '天津-移动-50' => 8064,
        '重庆-移动-50' => 8065,
        '河北-移动-50' => 8066,
        '山西-移动-50' => 8067,
        '内蒙古-移动-50' => 8068,
        '辽宁-移动-50' => 8069,
        '吉林-移动-50' => 8070,
        '黑龙江-移动-50' => 8071,
        '江苏-移动-50' => 8072,
        '浙江-移动-50' => 8073,
        '安徽-移动-50' => 8074,
        '福建-移动-50' => 8075,
        '江西-移动-50' => 8076,
        '山东-移动-50' => 8077,
        '河南-移动-50' => 8078,
        '湖北-移动-50' => 8079,
        '湖南-移动-50' => 8080,
        '广东-移动-50' => 8081,
        '广西-移动-50' => 8082,
        '海南-移动-50' => 8083,
        '四川-移动-50' => 8084,
        '贵州-移动-50' => 8085,
        '云南-移动-50' => 8086,
        '西藏-移动-50' => 8087,
        '陕西-移动-50' => 8088,
        '甘肃-移动-50' => 8089,
        '青海-移动-50' => 8090,
        '宁夏-移动-50' => 8091,
        '新疆-移动-50' => 8092,
        '北京-移动-100' => 8096,
        '上海-移动-100' => 8097,
        '天津-移动-100' => 8098,
        '重庆-移动-100' => 8099,
        '河北-移动-100' => 8100,
        '山西-移动-100' => 8101,
        '内蒙古-移动-100' => 8102,
        '辽宁-移动-100' => 8103,
        '吉林-移动-100' => 8104,
        '黑龙江-移动-100' => 8105,
        '江苏-移动-100' => 8106,
        '浙江-移动-100' => 8107,
        '安徽-移动-100' => 8108,
        '福建-移动-100' => 8109,
        '江西-移动-100' => 8110,
        '山东-移动-100' => 8111,
        '河南-移动-100' => 8112,
        '湖北-移动-100' => 8113,
        '湖南-移动-100' => 8114,
        '广东-移动-100' => 8115,
        '广西-移动-100' => 8116,
        '海南-移动-100' => 8117,
        '四川-移动-100' => 8118,
        '贵州-移动-100' => 8119,
        '云南-移动-100' => 8120,
        '西藏-移动-100' => 8121,
        '陕西-移动-100' => 8122,
        '甘肃-移动-100' => 8123,
        '青海-移动-100' => 8124,
        '宁夏-移动-100' => 8125,
        '新疆-移动-100' => 8126,
        '山西-联通-200' => 813,
        '北京-移动-200' => 8164,
        '上海-移动-200' => 8165,
        '天津-移动-200' => 8166,
        '重庆-移动-200' => 8167,
        '河北-移动-200' => 8168,
        '山西-移动-200' => 8169,
        '内蒙古-移动-200' => 8170,
        '辽宁-移动-200' => 8171,
        '吉林-移动-200' => 8172,
        '黑龙江-移动-200' => 8173,
        '江苏-移动-200' => 8174,
        '浙江-移动-200' => 8175,
        '安徽-移动-200' => 8176,
        '福建-移动-200' => 8177,
        '江西-移动-200' => 8178,
        '山东-移动-200' => 8179,
        '河南-移动-200' => 8180,
        '湖北-移动-200' => 8181,
        '湖南-移动-200' => 8182,
        '广东-移动-200' => 8183,
        '广西-移动-200' => 8184,
        '海南-移动-200' => 8185,
        '四川-移动-200' => 8186,
        '贵州-移动-200' => 8187,
        '云南-移动-200' => 8188,
        '西藏-移动-200' => 8189,
        '陕西-移动-200' => 8190,
        '甘肃-移动-200' => 8191,
        '青海-移动-200' => 8192,
        '宁夏-移动-200' => 8193,
        '新疆-移动-200' => 8194,
        '北京-联通-200' => 831,
        '内蒙古-联通-200' => 849,
        '天津-联通-200' => 867,
        '宁夏-联通-50' => 884,
        '宁夏-联通-100' => 885,
        '宁夏-联通-200' => 887,
        '浙江-联通-200' => 905,
        '江苏-联通-200' => 923,
        '广西-联通-200' => 941,
        '山东-联通-200' => 959,
    ];

    private $errorMap = [
        '0000' => '下单成功',
        '0001' => '支付失败',
        '0002' => '未知错误',
        '0999' => '未开通直冲功能',
        '1000' => '下单失败',
        '1001' => '传入参数不完整',
        '1002' => '验证摘要串验证失败',
        '1005' => '没有对应充值产品',
        '1006' => '系统异常，请稍后重试',
        '1007' => '账户余额不足',
        '1008' => '此产品超出当天限额',
        '1010' => '产品与手机号不匹配',
        '1011' => '定单号不允许重复',
        '1013' => '暂不可充值',
        '1015' => '无法查到对应号段',
        '1017' => '电信手机10秒内不能重复充值',
        '1020' => '号码不支持流量充值卡',
        '1022' => '充值号码格式错误',
        '1028' => '下单接口请求次数超限',
    ];

    /**
     * 创建订单
     *
     * @params
     * sub_order_id 系统订单号
     * amount 充值金额
     * mobile 充值号码
     * 
     * $return  false/供应商订单号
     * 
     * 下单成功
     * Array
    (
        [prodid] => 8075
        [orderid] => 1
        [tranid] => EDO2220111170637692822
        [resultno] => 0000
        [mark] => 
        [verifystring] => 8abda4ee4c61b1bb09e7fdd8eca7ca61
    )
     */
    public function create($order)
    {
        $supplier_order_no = '';

        $segment = $this->accsegment($order['mobile']);
        if (false === $segment) {
            $status = self::FAIL;
            $remark = '号码不支持1';
            return compact('status', 'supplier_order_no', 'remark');
        }
        $segment .= '-' . fen2yuan($order['amount']);
        if (empty($this->product[$segment])) {
            $status = self::FAIL;
            $remark = '号码不支持2';

            return compact('status', 'supplier_order_no', 'remark');
        }

        $params = [
            'prodid' => $this->product[$segment],
            'agentid' => $this->info['app_id'],
            'backurl' => '',
            'returntype' => 2,
            'orderid' => $order['sub_order_id'],
            'mobilenum' => $order['mobile'],
            'source' => 'esales',
            'mark' => '',
        ];
        $params['verifystring'] = $this->getSign($params);

        $url = $this->info['url'] . '/esales2/directfill/directFill.do?' . http_build_query($params);
        $res = curlGet($url, null, 5, true);
        $res = xml2arr($res);

        $data = $res['items']['item'] ?? [];
        $res = [];
        foreach ($data as $v) {
            $res[$v['@attributes']['name']] = urldecode($v['@attributes']['value']);
        }

        $supplier_order_no = '';
        $resultno = $res['resultno'] ?? '21';
        $remark = $this->getErrorByCode($resultno);
        switch ($resultno) {
            case '0000': // '下单成功', 已扣款
                $status = self::SUCCESS;
                $supplier_order_no = $res['tranid'] ?? '';
                break;
            case '1007': // '账户余额不足', 未扣款
                $status = self::LACK_OF_MONEY;
                break;
            case '0001': // '支付失败', 未扣款
            case '0999': // '未开通直冲功能', 未扣款
            case '1000': // '下单失败', 未扣款
            case '1001': // '传入参数不完整', 未扣款
            case '1002': // '验证摘要串验证失败', 未扣款
            case '1005': // '没有对应充值产品', 未扣款
            case '1008': // '此产品超出当天限额', 未扣款
            case '1010': // '产品与手机号不匹配', 未扣款
            case '1013': // '暂不可充值', 未扣款
            case '1015': // '无法查到对应号段', 未扣款
            case '1020': // '号码不支持流量充值卡', 未扣款
            case '1022': // '充值号码格式错误', 未扣款
            case '1028': // '下单接口请求次数超限', 未扣款
                $status = self::FAIL;
                break;
            case '0002': // '未知错误', 扣款状态未知
            case '1006': // '系统异常，请稍后重试', 扣款状态未知
            case '1011': // '定单号不允许重复', 未扣款
            case '1017': // '电信手机10秒内不能重复充值', 未扣款
                $status = self::NEED_CONFIRM;
                break;
            default:
                $status = self::NEED_RETRY;
                break;
        }

        return compact('status', 'supplier_order_no', 'remark');
    }

    /**
     * 话费充值产品查询
     */
    public function queryProduct()
    {
        $params = [
            'agentid' => $this->info['app_id'],
            'source' => 'esales',
        ];
        $params['verifystring'] = $this->getSign($params);
        $url = $this->info['url'] . '/esales2/prodquery/directProduct.do?' . http_build_query($params);
        $res = curlGet($url);
        $res = xml2arr($res);
        if (empty($res['products'])) {
            return false;
        }

        $products = [];
        foreach ($res['products'] as $v) {
            $p = [];
            foreach ($v['product'] as $v2) {
                $p[$v2['@attributes']['name']] = urldecode($v2['@attributes']['value']);
            }
            $products[] = $p;
        }
        return $products;
    }

    /**
     * 号段查询接口
     */
    public function accsegment($mobile)
    {
        $params = [
            'agentid' => $this->info['app_id'],
            'source' => 'esales',
            'mobilenum' => $mobile,
        ];
        $params['verifystring'] = $this->getSign($params);
        $url = $this->info['url'] . '/esales2/accegment/accsegment.do?' . http_build_query($params);
        $xml = curlGet($url);
        $res = xml2arr($xml);

        // doLog('北京高阳号段查询接口,'.__LINE__.',请求日志,url='.$url.',xml='.$xml.',解析xml返回值'.json_encode($res, JSON_UNESCAPED_UNICODE));

        if (empty($res['acc']['mobile'])) {
            return false;
        }
        $res = $res['acc']['mobile'];

        $data = [
            'provincename' => '',
            'isptype' => '',
        ];
        foreach ($res as $v) {
            $data[$v['@attributes']['name']] = urldecode($v['@attributes']['value']);
        }
        return $data['provincename'] . '-' . $data['isptype'];
    }

    /**
     * 查询余额
     * 
     * 单位：分
     */
    public function queryAmount()
    {
        $params = [
            'agentid' => $this->info['app_id'],
        ];
        $params['verifystring'] = $this->getSign($params);
        $url = $this->info['url'] . '/esales2/querypurse/purse.do?' . http_build_query($params);
        $xml = curlGet($url);
        $res = xml2arr($xml);
        if (empty($res['items']['item'])) {
            $this->error = '查询频繁';
            return false;
        }

        $data = [
            'code' => 1,
        ];
        foreach ($res['items']['item'] as $v) {
            $data[$v['@attributes']['name']] = urldecode($v['@attributes']['value']);
        }

        if ($data['code'] != 0 || !isset($data['balance'])) {
            $this->error = '查询频繁。';
            return false;
        }
        return yuan2fen($data['balance']);
    }

    /**
     * 订单查询
     */
    public function query($orderId)
    {
        $url = $this->info['url'] . '/api/mobile';
        $params = [
            'type' => 'quanmama.mobile.order.query',
            'app_key' => $this->appKey,
            'out_trade_no' => $orderId,
            'timestamp' => time(),
        ];
        $params['sign'] = $this->getSign($params);
        $res = curlPost($url, $params);
        $res = json_decode($res, true);
        return $res;
    }

    /**
     * 生成签名
     */
    public function getSign($params)
    {
        if (isset($params['verifystring'])) {
            unset($params['verifystring']);
        }
        $str = '';
        foreach ($params as $k => $v) {
            $str .= $k . '=' . $v . '&';
        }
        $str .= 'merchantKey=' . $this->info['app_secret'];
        return md5($str);
    }

    /**
     * 订单回调
     * {"status":"2","orderid":"7","ordermoney":"50.00","verifystring":"7899eb5d7f75e2c00fcb2db2b3481261","mobileBalance":"0.00"}
     */
    public function notify($params)
    {
        $insert = [
            'sub_order_id' => $params['orderid'] ?? '',
            'params' => json_encode($params, JSON_UNESCAPED_UNICODE),
            'result' => 'SUCCESS'
        ];

        $fields = [
            'orderid', 'status', 'ordermoney', 'verifystring',
        ];
        foreach ($fields as $field) {
            if (!isset($params[$field])) {
                $insert['result'] = '缺少参数【' . $field . '】';
                Db::name($this->notifyTable)->insert($insert);
                return $params['status'] ?? 'FAIL';
            }
        }

        $signStr = sprintf(
            "orderid=%s&status=%s&ordermoney=%s&merchantKey=%s",
            $params['orderid'],
            $params['status'],
            $params['ordermoney'],
            $this->info['app_secret'],
        );
        $sign = md5($signStr);
        if ($sign !== $params['verifystring']) {
            $insert['result'] = '验签失败';
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }

        $order = Db::name('mobile_order')
            ->where('sub_order_id', $params['orderid'])
            ->where('mobile_supplier_id', $this->info['id'])
            ->find();
        if (empty($order)) {
            $insert['result'] = '订单不存在';
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }

        if (in_array($order['supplier_status'], [3, 4, 99])) {
            $insert['result'] = '已经成功过';
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }

        if ($order['supplier_status'] != 2) {
            $insert['result'] = '订单状态有误：' . $order['supplier_status'];
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }

        $amount = fen2yuan($order['amount']);
        if ($params['ordermoney'] > $amount) {
            $insert['result'] = '到账金额大于充值金额：' . $params['ordermoney'] . ' -- ' . $amount;
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }

        // 供应商订单状态：1订单未创建 2订单已创建 3充值成功 4充值失败
        // 2充值成功 3部分成功 4充值失败
        $supplierStatusMap = [
            2 => 3, // 1已充值 --> 3充值成功
            3 => 3, // 3部分充值成功 --> 5部分充值成功
            4 => 99, // 2充值失败 --> 充值失败，等待重试
        ];
        $supplierStatus = $supplierStatusMap[$params['status']] ?? 2;
        if ($order['supplier_status'] == $supplierStatus) {
            Db::name($this->notifyTable)->insert($insert);
            return $params['status'];
        }
        $update = [
            'supplier_status' => $supplierStatus,
            'finish_time' => time(),
        ];
        if ($supplierStatus == 99) {
            // $update['refund_status'] = 2;   // 充值失败，退款
            $order['notify_url'] = '';  // 失败通知先不发
        }

        Db::name($this->notifyTable)->insert($insert);

        Db::startTrans();
        try {
            // 如果是返佣模式，将订单结算方式改成待结算
            if ($supplierStatus == 3 && $order['settle_type'] == SETTLE_TYPE_PROFIT) {
                if ($order['profit'] == 0) {
                    $update['settle_status'] = 3;
                } elseif ($order['settle_status'] == 1) {
                    $update['settle_status'] = 2;
                }
            }

            Mobile::handleNotify($order, $update);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            $insert['result'] = '订单更新失败' . $order['id'] . '。' . $e->getMessage();
            Db::name($this->notifyTable)->insert($insert);
        }

        return $params['status'];
    }

    public function getErrorByCode($code)
    {
        return $this->errorMap[$code] ?? '下单失败2';
    }
}
